#include "ImageLabel.h"
#include <QPainter>         // 用于绘制图形
#include <QMenu>            // 用于上下文菜单
#include <QDialog>          // 用于弹出对话框查看大图
#include <QVBoxLayout>      // 用于布局大图对话框
#include <QLabel>           // 用于显示图像
#include <cmath>            // 用于几何计算（如 hypot）
#include <QMouseEvent>
#include <QDebug>

// 构造函数，启用鼠标跟踪功能
ImageLabel::ImageLabel(QWidget *parent) : QLabel(parent) {
    setMouseTracking(true);  // 即使不按下鼠标也能接收到 mouseMoveEvent
}
// 【新增】通用的 setOriginalPixmap 函数，并移除 setOriginalPixmapD1 和 setOriginalPixmapD2
void ImageLabel::setOriginalPixmap(const QPixmap &pixmap) {
    originalPixmap = pixmap;
    if (!originalPixmap.isNull()) {
        scaledPixmap =originalPixmap.scaled(size(),
                                             Qt::KeepAspectRatio, Qt::SmoothTransformation);
        setPixmap(scaledPixmap);
    } else {
        scaledPixmap = QPixmap();
        clear(); // 清除显示的图像
    }
    update();
}
// 析构函数
ImageLabel::~ImageLabel() {}

void ImageLabel::mousePressEvent(QMouseEvent *ev) {
    if (ev->button() == Qt::LeftButton && !closed) {
        QPoint imgPos = mapToImage(ev->pos());
        if (!points.empty()) {
            // 注意：闭合判断应该在控件坐标系下进行，因为用户看到的是控件
            double dist = std::hypot(ev->pos().x() - mapToWidget(points[0]).x(), ev->pos().y() - mapToWidget(points[0]).y());
            if (dist < 10) { // 如果靠近第一个点，则闭合
                closed = true;
                update();
                return;
            }
        }
        points.push_back(imgPos); // 存储原图坐标
        update();
    }
}

void ImageLabel::mouseMoveEvent(QMouseEvent *ev) {
    if (!closed) {
        currentPos = ev->pos();
        update();
    }
}

void ImageLabel::paintEvent(QPaintEvent *event) {
    QLabel::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    if (!points.empty()) {
        painter.setPen(QPen(Qt::red, 2));
        for (const auto &point : points) {
            painter.drawEllipse(mapToWidget(point), 3, 3); // 转换回控件坐标进行绘制
        }

        painter.setPen(QPen(Qt::green, 1));
        for (size_t i = 0; i < points.size() - 1; ++i) {
            painter.drawLine(mapToWidget(points[i]), mapToWidget(points[i + 1]));
        }

        if (!closed) {
            painter.drawLine(mapToWidget(points.back()), currentPos);
        } else {
            painter.drawLine(mapToWidget(points.back()), mapToWidget(points.front()));
            QVector<QPoint> widgetPoints;
            for(const auto& p : points) {
                widgetPoints.append(mapToWidget(p));
            }
            QPolygon poly(widgetPoints);
            painter.setBrush(QColor(0, 255, 0, 100));
            painter.drawPolygon(poly);
        }
    }
}

void ImageLabel::clearPoints() {
    points.clear();
    closed = false;
    update();
}

// 将控件（QLabel）中的坐标映射为图像（originalPixmap1）中的实际像素坐标
// 【修改】mapToImage 和 mapToWidget 使用通用成员
QPoint ImageLabel::mapToImage(const QPoint& widgetPos) const {
    if (originalPixmap.isNull()) return {};
    QSize labelSize = size();
    QSize imgSize = scaledPixmap.size();
    int offsetX = (labelSize.width() - imgSize.width()) / 2;
    int offsetY = (labelSize.height() - imgSize.height()) / 2;
    QPoint imgPos = widgetPos - QPoint(offsetX, offsetY);
    double scaleX = double(originalPixmap.width()) / imgSize.width();
    double scaleY = double(originalPixmap.height()) / imgSize.height();
    return QPoint(int(imgPos.x() * scaleX), int(imgPos.y() * scaleY));
}

// 将图像坐标映射为控件坐标（用于绘图显示）
QPoint ImageLabel::mapToWidget(const QPoint& imgPt) const {
    if (originalPixmap.isNull()) return {};
    QSize labelSize = size();
    QSize imgSize = scaledPixmap.size();
    int offsetX = (labelSize.width() - imgSize.width()) / 2;
    int offsetY = (labelSize.height() - imgSize.height()) / 2;
    double scaleX = double(imgSize.width()) / originalPixmap.width();
    double scaleY = double(imgSize.height()) / originalPixmap.height();
    return QPoint(int(imgPt.x() * scaleX) + offsetX, int(imgPt.y() * scaleY) + offsetY);
}

// 获取当前绘制的点集合（多边形模式）
const std::vector<QPoint>& ImageLabel::getPoints() const {
    return points;
}